//
//$Id: qap_ga.h 441 2010-04-09 17:27:20Z Oleg.Bulychov $
#pragma once

#include "projects/qap/qap.h"
#include "solvers/ga/ga_common.h"

//__________________________________________________________________________________
//__________________________________________________________________________________

inline bool Present(Array<int> const& v, int const ind, int const data)
{
    for (int i = 0; i < ind; ++i)
        if (v[i] == data)
            return true;

    return false;
}

template<>
struct solution<QAP_Solution, ga_tag>:
    public QAP_Solution
{
    Array<int> tmp_;
public:
    mutable double wheel_sector_;

    template<class E>
    void cross(E* env, uniform_random& rnd, solution<QAP_Solution, ga_tag>& genome)
    {
        int n = int(p_.size());
        int k = rnd.next_UInt(n); // cross point

        tmp_ = p_;
        genome.tmp_ = genome.p_;

        //for (int i = k + 1; i < n; ++i)
        //{
        //    for (int j = 0; j < n; ++j) // scan for 
        //    {
        //        if (!Present(tmp_, i, genome.p_[j]))
        //        {
        //            tmp_[i] = genome.p_[j];
        //        }
        //        if (!Present(genome.tmp_, i, p_[j]))
        //        {
        //            genome.tmp_[i] = p_[j];
        //        }
        //    }
        //}
        for (int i = k + 1; i < n; ++i)
        {
            for (int j = 0; j < n; ++j) // scan for 
            {
                if (!Present(tmp_, i, genome.p_[j]))
                {
                    tmp_[i] = genome.p_[j];
                    break;
                }
            }

            for (int j = 0; j < n; ++j) // scan for 
            {
                if (!Present(genome.tmp_, i, p_[j]))
                {
                    genome.tmp_[i] = p_[j];
                    break;
                }
            }
        }

        p_.swap(tmp_);
        genome.p_.swap(genome.tmp_);

        //std::cout << "offspring:";
        //print(std::cout, env);

        changed_ = genome.changed_ = true;
    }


    template<class E>
    void mutate(E* env, uniform_random& rnd, double mutationProbability)
    {
        if (rnd.next_Double() < mutationProbability)
        {
            int n = int(p_.size());
            for (int k = 0; k < env->cfg_.permutations_; ++k)
            {
                int i = rnd.next_UInt(n);
                int j = rnd.next_UInt(n);
                std::swap(p_[i], p_[j]);
            }

            changed_ = true;
        }
    }

    TCostType get_Fitness() const { return get_Cost(); }
};
//__________________________________________________________________________________

//EOF!
